package com.frejoys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.frejoys.common.dto.admin.*;
import com.frejoys.common.dto.common.IdDto;
import com.frejoys.common.enums.EShelves;
import com.frejoys.common.enums.EStatus;
import com.frejoys.common.error.HttpStatus;
import com.frejoys.common.exception.GeneralException;
import com.frejoys.common.util.TimeUtil;
import com.frejoys.common.vo.admin.AdminStoreActivityInfoVo;
import com.frejoys.common.vo.admin.AdminStoreActivityPageVo;
import com.frejoys.dao.entity.Activity;
import com.frejoys.dao.entity.Store;
import com.frejoys.dao.entity.StoreActivity;
import com.frejoys.dao.entity.StoreActivityQueue;
import com.frejoys.dao.mapper.ActivityMapper;
import com.frejoys.dao.mapper.StoreActivityMapper;
import com.frejoys.dao.mapper.StoreMapper;
import com.frejoys.service.StoreActivityService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

// 店家
@Service
@RequiredArgsConstructor
public class StoreActivityServiceImpl extends ServiceImpl<StoreActivityMapper, StoreActivity> implements StoreActivityService {

    private final ActivityMapper activityMapper;

    private final StoreMapper storeMapper;

    private final StoreActivityMapper storeActivityMapper;

    @Override
    public List<StoreActivity> getTaskValidActivity(Integer page, Integer size, Integer type) {
        Page p = new Page<>(page, size);
        p.setSearchCount(false);

        Integer nt = TimeUtil.unixTime();

        LambdaQueryWrapper<StoreActivity> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(StoreActivity::getId, StoreActivity::getStoreId, StoreActivity::getMoney, StoreActivity::getRebateMaxMoney);
        wrapper.eq(StoreActivity::getStatus, EStatus.on.getValue());
        wrapper.eq(StoreActivity::getShelves, EShelves.onSale.getValue());
        wrapper.lt(StoreActivity::getStartTime, nt);
        wrapper.gt(StoreActivity::getEndTime, nt);
        wrapper.gt(StoreActivity::getMoney, 0);
        if (type != null) {
            wrapper.eq(StoreActivity::getType, type);
        }

        return baseMapper.selectPage(p, wrapper).getRecords();
    }

    @Override
    public StoreActivity getInfo(Integer id) {
        return baseMapper.selectById(id);
    }

    @Override
    public boolean addInfo(StoreActivityAddDto dto) {

        if (dto.getRebateMaxMoney().compareTo(BigDecimal.ZERO) != 1){
            throw new GeneralException(HttpStatus.rebateMaxMoneyError);
        }

        Float totalRatio = dto.getRebateRatio() + dto.getPromotionRatio();
        if (totalRatio < 0 || totalRatio > 100) {
            throw new GeneralException(HttpStatus.rebateRatioError);
        }

        if (dto.getStartRatio() < 1 || dto.getStartRatio() > 100 || dto.getEndRatio() < 1 || dto.getEndRatio() > 100) {
            throw new GeneralException(HttpStatus.startRatioAndEndRatioError);
        }

        if (dto.getStartRatio() > dto.getEndRatio()) {
            throw new GeneralException(HttpStatus.startRatioGreaterThanEndRatioError);
        }

        //同一时刻存在上架一个活动
        Integer num = storeActivityMapper.getStoreActivity(dto.getStoreId(), TimeUtil.unixTime(dto.getStartTime()), TimeUtil.unixTime(dto.getEndTime()));
        if(num > 0){
            throw new GeneralException(HttpStatus.storeActivityHasExit);
        }

        StoreActivity storeActivity = BeanUtil.copyProperties(dto, StoreActivity.class);
        storeActivity.setShelves(EShelves.offShelf.getValue());
        storeActivity.setMoney(BigDecimal.ZERO);
        storeActivity.setTotalMoney(BigDecimal.ZERO);
        if (StrUtil.isNotEmpty(dto.getStartTime()) && StrUtil.isNotEmpty(dto.getEndTime())) {
            storeActivity.setStartTime(TimeUtil.unixTime(dto.getStartTime()));
            storeActivity.setEndTime(TimeUtil.unixTime(dto.getEndTime()));
        }
        return save(storeActivity);
    }

    @Override
    public boolean upInfo(StoreActivityUpDto dto) {

        if (dto.getRebateMaxMoney().compareTo(BigDecimal.ZERO) != 1){
            throw new GeneralException(HttpStatus.rebateMaxMoneyError);
        }

        Float totalRatio = dto.getRebateRatio() + dto.getPromotionRatio();
        if (totalRatio < 0 || totalRatio > 100) {
            throw new GeneralException(HttpStatus.rebateRatioError);
        }

        if (dto.getStartRatio() < 1 || dto.getStartRatio() > 100 || dto.getEndRatio() < 1 || dto.getEndRatio() > 100) {
            throw new GeneralException(HttpStatus.startRatioAndEndRatioError);
        }

        if (dto.getStartRatio() > dto.getEndRatio()) {
            throw new GeneralException(HttpStatus.startRatioGreaterThanEndRatioError);
        }

        //同一时刻存在上架一个活动
        Integer num = storeActivityMapper.getStoreActivity(dto.getStoreId(), TimeUtil.unixTime(dto.getStartTime()), TimeUtil.unixTime(dto.getEndTime()));
        if(num > 0){
            throw new GeneralException(HttpStatus.storeActivityHasExit);
        }

        boolean inProgress = baseMapper.exists(Wrappers.<StoreActivity>lambdaQuery().eq(StoreActivity::getId, dto.getId())
                .and(qw -> {
                    qw.eq(StoreActivity::getShelves, EShelves.onSale.getValue());
                    qw.or();
                    qw.eq(StoreActivity::getShelves, EShelves.applyfor.getValue());
                }));
        if (inProgress) {
            throw new GeneralException(HttpStatus.onSaleEditError);
        }

        LambdaUpdateWrapper<StoreActivity> wrapper = new LambdaUpdateWrapper<>();

        wrapper.eq(StoreActivity::getId, dto.getId());

        if (dto.getRebateRatio() != null) {
            wrapper.set(StoreActivity::getRebateRatio, dto.getRebateRatio());
        }

        if (dto.getRebateMaxMoney() != null) {
            wrapper.set(StoreActivity::getRebateMaxMoney, dto.getRebateMaxMoney());
        }

        if (dto.getPromotionRatio() != null) {
            wrapper.set(StoreActivity::getPromotionRatio, dto.getPromotionRatio());
        }
        if (dto.getStartRatio() != null) {
            wrapper.set(StoreActivity::getStartRatio, dto.getStartRatio());
        }
        if (dto.getEndRatio() != null) {
            wrapper.set(StoreActivity::getEndRatio, dto.getEndRatio());
        }

        if (StrUtil.isNotEmpty(dto.getStartTime()) && StrUtil.isNotEmpty(dto.getEndTime())) {
            wrapper.set(StoreActivity::getStartTime, TimeUtil.unixTime(dto.getStartTime()));
            wrapper.set(StoreActivity::getEndTime, TimeUtil.unixTime(dto.getEndTime()));
        }

        if (dto.getType() != null) {
            wrapper.set(StoreActivity::getType, dto.getType());
        }

        return update(wrapper);
    }

    @Override
    public boolean delInfo(Integer id) {
        LambdaUpdateWrapper<StoreActivity> adUpdateWrapper = new LambdaUpdateWrapper<>();
        adUpdateWrapper.set(StoreActivity::getStatus, EStatus.off.getValue());
        adUpdateWrapper.eq(StoreActivity::getId, id);
        return update(adUpdateWrapper);
    }

    @Override
    public List<StoreActivity> getList(LambdaQueryWrapper<StoreActivity> wrapper) {
        return baseMapper.selectList(wrapper);
    }

    /**
     * 后台查询店铺活动
     *
     * @param dto
     */
    @Override
    public IPage<AdminStoreActivityPageVo> pageList(StoreIdAndNameDto dto) {
        Page<StoreActivity> page = new Page<>(dto.getPage(), dto.getSize());
        LambdaQueryWrapper<StoreActivity> wrapper = Wrappers.lambdaQuery();
        if (dto.getStoreId() != null){
            wrapper.eq(StoreActivity::getStoreId,dto.getStoreId());
        }
        if (StrUtil.isNotEmpty(dto.getName())){
            List<Store> stores = storeMapper.getStoreNameById(dto.getName());
            if (stores.isEmpty()){
                return new Page<>();
            }
            List<Integer> ids = stores.stream().map(Store::getId).toList();
            wrapper.in(StoreActivity::getStoreId,ids);
        }
        Page<StoreActivity> selectPage = baseMapper.selectPage(page, wrapper);
        IPage<AdminStoreActivityPageVo> storeActivityPage = selectPage.convert(storeActivity -> BeanUtil.copyProperties(storeActivity, AdminStoreActivityPageVo.class));
        List<AdminStoreActivityPageVo> storeActivities = storeActivityPage.getRecords();

        if (CollectionUtil.isNotEmpty(storeActivities)) {

            List<Integer> types = storeActivities.stream().map(AdminStoreActivityPageVo::getType).toList();

            List<Integer> storeIds = storeActivities.stream().map(AdminStoreActivityPageVo::getStoreId).toList();

            List<Store> storeNameList = storeMapper.getStoreNameList(storeIds);

            LambdaQueryWrapper<Activity> activityWrapper = Wrappers.lambdaQuery();
            activityWrapper.select(Activity::getType, Activity::getName).in(Activity::getType, types);
            List<Activity> activities = activityMapper.selectList(activityWrapper);
            Map<Integer, String> activityMap = new HashMap<>();
            if (CollectionUtil.isNotEmpty(activities)) {
                activityMap = activities.stream().collect(Collectors.toMap(Activity::getType, Activity::getName));
            }
            Map<Integer, String> storeMap = new HashMap<>();
            if (CollectionUtil.isNotEmpty(storeNameList)) {
                storeMap = storeNameList.stream().collect(Collectors.toMap(Store::getId, Store::getName));
            }

            for (AdminStoreActivityPageVo sa : storeActivities) {
                sa.setActivityName(activityMap.get(sa.getType()));
                sa.setStoreName(storeMap.get(sa.getStoreId()));
            }
        }

        return storeActivityPage;
    }

    /**
     * 根据店铺活动id获取店铺活动详情
     *
     * @param dto
     */
    @Override
    public AdminStoreActivityInfoVo getInfo(IdDto dto) {
        StoreActivity storeActivity = baseMapper.selectById(dto.getId());
        AdminStoreActivityInfoVo infoVo = BeanUtil.copyProperties(storeActivity, AdminStoreActivityInfoVo.class);
        infoVo.setActivityName(activityMapper.getNameByType(infoVo.getType()));
        Store store = storeMapper.getNameInfo(infoVo.getStoreId());
        infoVo.setStoreName(ObjectUtil.isEmpty(store) ? "" : store.getName());
        return infoVo;
    }

    @Override
    public boolean upStoreActivityShelves(UpShelvesDto dto) {


        //校验同一时刻只能上架一个活动
        if (dto.getShelves() == EShelves.onSale.getValue()){
            StoreActivity storeActivity = storeActivityMapper.selectOne(Wrappers.<StoreActivity>lambdaQuery().select(StoreActivity::getStoreId, StoreActivity::getStartTime,
                            StoreActivity::getEndTime)
                    .eq(StoreActivity::getId, dto.getId()).last(" limit 1"));

            Store store = storeMapper.selectOne(Wrappers.<Store>lambdaQuery().select(Store::getId,Store::getShelves)
                    .eq(Store::getId, storeActivity.getStoreId()).last(" limit 1"));

            if (ObjectUtil.isEmpty(store)) {
                throw new GeneralException(HttpStatus.storeNotFound);
            }

            //同一时刻只能上架一个活动
            Integer num = storeActivityMapper.getStoreActivity(storeActivity.getStoreId(), storeActivity.getStartTime(), storeActivity.getEndTime());

            if(num > 0){
                throw new GeneralException(HttpStatus.storeActivityHasExit);
            }
        }

        //编辑状态
        LambdaUpdateWrapper<StoreActivity> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(StoreActivity::getId,dto.getId());
        updateWrapper.set(StoreActivity::getShelves,dto.getShelves());
        baseMapper.update(updateWrapper);
        return true;
    }


    @Override
    public boolean upStoreActivity(StoreActivityUpDto dto) {

        if (dto.getRebateMaxMoney().compareTo(BigDecimal.ZERO) != 1){
            throw new GeneralException(HttpStatus.rebateMaxMoneyError);
        }

        Float totalRatio = dto.getRebateRatio() + dto.getPromotionRatio();
        if (totalRatio < 0 || totalRatio > 100) {
            throw new GeneralException(HttpStatus.rebateRatioError);
        }

        if (dto.getStartRatio() < 0 || dto.getStartRatio() > 100 || dto.getEndRatio() < 0 || dto.getEndRatio() > 100) {
            throw new GeneralException(HttpStatus.outOfRangeError);
        }

        if (dto.getStartRatio() > dto.getEndRatio()) {
            throw new GeneralException(HttpStatus.startRatioGreaterThanEndRatioError);
        }

        //同一时刻存在上架一个活动
        Integer num = storeActivityMapper.getStoreActivityNotOwn(dto.getId(),dto.getStoreId(), TimeUtil.unixTime(dto.getStartTime()), TimeUtil.unixTime(dto.getEndTime()));
        if(num > 0){
            throw new GeneralException(HttpStatus.storeActivityHasExit);
        }

        LambdaUpdateWrapper<StoreActivity> wrapper = new LambdaUpdateWrapper<>();

        wrapper.eq(StoreActivity::getId, dto.getId());

        if (dto.getRebateRatio() != null) {
            wrapper.set(StoreActivity::getRebateRatio, dto.getRebateRatio());
        }

        if (dto.getRebateMaxMoney() != null) {
            wrapper.set(StoreActivity::getRebateMaxMoney, dto.getRebateMaxMoney());
        }

        if (dto.getPromotionRatio() != null) {
            wrapper.set(StoreActivity::getPromotionRatio, dto.getPromotionRatio());
        }
        if (dto.getStartRatio() != null) {
            wrapper.set(StoreActivity::getStartRatio, dto.getStartRatio());
        }
        if (dto.getEndRatio() != null) {
            wrapper.set(StoreActivity::getEndRatio, dto.getEndRatio());
        }

        if (StrUtil.isNotEmpty(dto.getStartTime()) && StrUtil.isNotEmpty(dto.getEndTime())) {
            wrapper.set(StoreActivity::getStartTime, TimeUtil.unixTime(dto.getStartTime()));
            wrapper.set(StoreActivity::getEndTime, TimeUtil.unixTime(dto.getEndTime()));
        }

        if (dto.getType() != null) {
            wrapper.set(StoreActivity::getType, dto.getType());
        }
        if (dto.getAllowCount() != null){
            wrapper.set(StoreActivity::getAllowCount,dto.getAllowCount());
        }
        baseMapper.update(wrapper);
        return true;
    }

    @Override
    public List<StoreActivity> listInfo(StoreActivityListDto dto) {
        Page page = new Page<>(dto.getPage(), dto.getSize());
        page.setSearchCount(false);
        LambdaQueryWrapper<StoreActivity> queryWrapper = new LambdaQueryWrapper<>();
        return baseMapper.selectPage(page, queryWrapper).getRecords();
    }

}